//
//  TempUtilVC.swift
//  ZYA
//
//  Created by 邱仙凯 on 2022/8/3.
//  Copyright © 2025 aowang. All rights reserved.
//

import UIKit


// 缓存获取的动态菜单列表模板，给自定义按钮跳菜单使用
var cachedDynamicArray = [(String,[MainTempModel])]()

// 影响类型
enum EffectType:String {
    case setClear,
         setClearDetails,
         setDicValue = "setValue",
         setFieldAnnotation,
         setFieldType,// 暂未实现 切换类型
         setEnable,setDisable,
         setRequired,setUnRequired,
         setLovUrl,setLovField,setLovFieldBackfill,setMultichoice,
         setSelectData,setSelectFieldBackfill,
         setComputedExpression,
         setHidden,setShow,otherValue,
         setNumberCapital
}
// 自定义按钮类型
enum ZiDingType:String {
    case yunmou,
         api,
         web,
         lov,
         form,
         uniapp,
         flow // 渔美康定制审批流程查看
}
// lov型是 在列表上弹窗类似于lov的单纯展示信息
// 在路径字段里填写字段对应，然后在主表里配置lov类型的字段信息，整个结构和lov字段的配置类似


enum BtnJudgeStatus {
    case unControl,agree,disAgree // 没有控制    允许    不允许
}

struct TKey {
    static let  page = "page"
    static let  size = "size"
    static let  keyword = "keyword"
    static let  levelInfos1 = "levelInfos1"
    static let  levelInfos2 = "levelInfos2"
    static let  levelInfos3 = "levelInfos3"
    static let  openx = "openx"
    static let  groupShow = "groupShow" // 分组的头部显示
    
    static let  details = "details"
    static let  id_key = "id_key"
}



//主表小集体
struct TempEitem {
    var temp:TemplateModel? // 模板
    var item:FormItem? = nil// 持有所有控件
    var imgArray = [VideoImg]()// 附件数组
}
//细表小集体  不持有控件
struct DetailsTempCom {
    var temp = [TemplateModel]() // 模板
    var detailHeight:CGFloat = 0
    var dic = [String:Any]()
    var imgArray = [VideoImg]()// 附件数组
    
}

struct LianDHandler {
    var dic = [String:Any]() // 选中的标题
    var ldShowParam = "" // 展示参数
    var child = [LianDHandler]()
}


func getSortGroupVal(_ str:String,dicArr:[[String:Any]]) -> String {
    
    // 去空格  去换行 去$
    let tempStr = str.replacingOccurrences(of: "$", with: "")
    
    var result = ""
    var tempParam = ""
    var collecting = false
    tempStr.forEach { c in
        let s = String(c)
        if s == "{" {
            tempParam = ""
            collecting = true
        } else if s == "}" {
            collecting = false
            var realV = ""
            if tempParam.contains("a.") {
                realV =  any2Str(dicArr.first![tempParam.replacingOccurrences(of: "a.", with: "")])
            } else if tempParam.contains("s.") {
                let rK = tempParam.replacingOccurrences(of: "s.", with: "")
                
                let sA = dicArr.compactMap{doubleTran(any2Str($0[rK]))}.reduce(0,+).cleanZero
                realV =  "\(sA)"
                
            } else {
                realV =  any2Str(dicArr.first![tempParam])
                
            }
            KSLog("realV")
            KSLog(tempParam)
            KSLog(realV)
            result += realV
        } else {
            
            if collecting {
                tempParam += s
            } else {
                result += s
            }
        }
    }
    KSLog(result)
    // 处理的换行符不生效问题
    return result.replacingOccurrences(of: "\\n", with: "\n")
}







// 专门针对自定义按钮取值的临时写法
func getUrl4ziding(str:String,mainDic:[String:Any]) -> String {
    var realUrl = str.removeAllSapce.removeLineFeed
    
    realUrl = realUrl.replacingOccurrences(of: "${mobiletoken}", with: TOKEN)
    realUrl = realUrl.replacingOccurrences(of: "${mobileauthid}", with: AUTHID)
 
    
    var result = "" // 累计字符
    var param = "" // 参数字符
    var getPing = false // true 表示累计参数中
    realUrl.forEach { c in
        let s = String(c)
        if s == "$" {
            
        } else if s == "{" {
            param = ""
            getPing = true
        } else if s == "}" {
            
            if param.contains(".") { // 包含. 说明指定了位置
                let preFrom =  param.preChar(char: ".").unwrap
                let preSuf =  param.sufChar(char: ".").unwrap
                if preFrom == "a" {// 主表取值
                    let temp = any2Str(mainDic[preSuf])
                    result += temp
                } else { // 这里默认为p.取值
                    let temp = any2Str(getValueByKey(obj: USERINFO, key: preSuf.removeBrackets.removeDolendAt.camelName))
                    result += temp
                }
            } else {
                let temp = any2Str(mainDic[param])
                result += temp
                
            }
            getPing = false
        } else {
            if getPing {
                param += s
            } else {
                result += s
            }
            
        }
    }
    
    if !result.contains("http") {
        result = HTTPStr + result
    }
    
    
    return result
}

// 专门针对自定义uniapp按钮取值
func getUrl4zidingUniapp(str: String, mainDic: [String: Any]) -> String {
    var realUrl = str.removeAllSapce.removeLineFeed
    
    realUrl = realUrl.replacingOccurrences(of: "${mobiletoken}", with: TOKEN)
    realUrl = realUrl.replacingOccurrences(of: "${mobileauthid}", with: AUTHID)
 
    
    var result = "" // 累计字符
    var param = "" // 参数字符
    var getPing = false // true 表示累计参数中
    realUrl.forEach { c in
        let s = String(c)
        if s == "$" {
            
        } else if s == "{" {
            param = ""
            getPing = true
        } else if s == "}" {
            
            if param.contains(".") { // 包含. 说明指定了位置
                let preFrom =  param.preChar(char: ".").unwrap
                let preSuf =  param.sufChar(char: ".").unwrap
                if preFrom == "a" {// 主表取值
                    let temp = any2Str(mainDic[preSuf])
                    result += temp
                } else { // 这里默认为p.取值
                    let temp = any2Str(getValueByKey(obj: USERINFO, key: preSuf.removeBrackets.removeDolendAt.camelName))
                    result += temp
                }
            } else {
                let temp = any2Str(mainDic[param])
                result += temp
                
            }
            getPing = false
        } else {
            if getPing {
                param += s
            } else {
                result += s
            }
            
        }
    }
    
    return result
}


/**
 id 传值:
     生产("生产","2"),//养殖--生产
     购销管理("购销管理","3"),//养殖--种猪-购销管理
     设备管养("设备管养","3"),//养殖--种猪-设备管养
     生产管理("生产管理","3"),//养殖--种猪-设备管养
     繁殖管理("繁殖管理","3"),//养殖--种猪-繁殖管理
     日常管理("日常管理","5"),//环保
     车辆管理("车辆管理","6"),//物流
     安全("安全","7"),//安全
     办公("办公管理","11"),//办公

     异常预警("异常预警","2"),//异常预警
     饲料管理("饲料管理","8"),//饲料
     个人中心("个人中心","10"),//设置界面
     食品("食品","12"),//食品
     领导BI-饲料 13
 */
func getTempMenu(id:String,directory_nm:String = "",result:@escaping (([MeSuperModel])->())) {
    KSNetwork.shared.doRequest(API.temp(.getMenuTemplateInfoByModuleId(module_id: id,directory_nm: directory_nm))) {  (data:BaseResult<MeSuperModel>) in
        if data.flag == TRUE {
            if let infos = data.infoArrCombine {
                // 缓存配置菜单
                for xx in 0..<infos.count {
                    cachedDynamicArray.append((infos[xx].directory_nm.unwrap,infos[xx].tempArr))

                }
                result(infos)
            }
        } else {
            KSToast(data.errorCombine.unwrap)
        }
    }
}


// 查找匹配到附件模板的字段，并特殊处理
func findTempDicAndDeal(templateDic:[[String:Any]],item:TemplateModel?) -> [String:Any] {
    let fiArr = templateDic.filter { onex -> Bool in
        if any2Str(onex[TempSerialKeys.field_nm]) == item!.field_nm &&
            any2Str(onex[TempSerialKeys.zone]) == item!.zone &&
            any2Str(onex[TempSerialKeys.place_flag]) == item!.placeFlag &&
            any2Str(onex[TempSerialKeys.detail_nm]) == item!.detail_nm  {
            
            return true
        } else {
            
            return false
        }
    }
    var tdic = [String:Any]()
    if fiArr.count > 0 {
        let tempTdic = fiArr.first!
        // 新有安云的字段 带c_,但是这个接口只接收旧值，手动改回旧值字段
        for (key,value) in tempTdic {
            if key.contains("c_") {
                let newkey = key.replacingOccurrences(of: "c_", with: "")
 
                tdic.updateValue(value, forKey: newkey)
            } else {
                tdic.updateValue(value, forKey: key)
            }
         }
    }
    return tdic
}
// MARK: - 查询图片 通用模板
public func queryPicture_temp(templateDic:[[String:Any]],module_id:String,vouid:String,item:TemplateModel?,back:(([TempPicModel])->())?){
     
    if vouid.count == 0 {
        back!([])
        return
    }
    
    let tdic = findTempDicAndDeal(templateDic: templateDic, item: item)
    
    if OfflineFileBoard.isUseFileClipPlatform() {
        KSNetwork.shared.doRequest(API.temp(.queryPicClipInfo_temp(vou_id: vouid,module_id:module_id,templateData: dictionaryToJson(tdic))), successHandle: { (data:BaseResult<TempPicModel>) in
            if data.flag == TRUE {
                if let item = data.infoArrCombine {
                    back!(item)
                } else {
                    back!([])
                }
             
            } else {
                KSToast("查询附件出错，\n问题：\(data.errorCombine.unwrap)",duration: 1.5)
                back!([])
            }
            
        })
    } else {
        KSNetwork.shared.doRequest(API.temp(.queryPicInfo_temp(vou_id: vouid,module_id:module_id,templateData: dictionaryToJson(tdic))), successHandle: { (data:BaseResult<TempPicModel>) in
            if data.flag == TRUE {
                if let item = data.infoArrCombine {
                    back!(item)
                } else {
                    back!([])
                }
             
            } else {
                KSToast("查询附件出错，\n问题：\(data.errorCombine.unwrap)",duration: 1.5)
                back!([])
            }
            
        })
    }  
    
}

// MARK: - 上传图片 通用模板版
public func tempUploadFileFun(templateDic: [[String:Any]], module_id: String, module_nm: String, imgArray: [VideoImg], vouId: String, item: TemplateModel?, success: @escaping (() -> Void), error:@escaping ((KSNetworkError) -> Void)) {
    // MARK: - 图片上传
    
  
    
   
    
    let newFile = imgArray.filter { $0.idkey == "" || $0.idkey == nil }
    if newFile.count < 1 { //  没有图片可以传
        success()
    } else {
        var totalDicArr = [[String:String]]()
        var totalJsonArr = [String]()
        //        let caArr = newFile.filter{ $0.type == .image && $0.imageTp == .camera }
        if newFile.count > 0 {
            
            for _ in 0..<newFile.count {
                
                var dic:[String:String] = [:]
                dic.updateValue(UIDevice.current.modelName, forKey: "z_phone_model")
                dic.updateValue("1", forKey: "z_is_take_photo")
                dic.updateValue("", forKey: "z_original_pic_name")
                let coor = LocationTool.shared.getCoor()
                
                dic.updateValue( "\(coor.longitude)", forKey: "z_longitude")
                dic.updateValue( "\(coor.latitude)", forKey: "z_latitude")
                
                
                dic.updateValue( LocationTool.shared.getAddress(), forKey: "z_address")
                dic.updateValue(Date.nowTimeToMinute, forKey: "z_original_time")
                
                totalDicArr.append(dic)
            }
            dealLibraryAndNet()
            
            
        } else {
            dealLibraryAndNet()
        }
        
        func dealLibraryAndNet() {
            let assets = newFile.filter{ $0.type == .image && $0.imageTp == .photoLibrary }.compactMap {$0.asset}
            getDicFromAssets(assets: assets) { dicArr in
                totalDicArr += dicArr
                
                
                totalJsonArr = totalDicArr.compactMap { dictionaryToJson($0) }
                
                var deJson = totalJsonArr.joined(separator: ",")
                deJson = "[\(deJson)]"
                
                let tdic = findTempDicAndDeal(templateDic: templateDic, item: item)
                // 后端解析不了，要把标准的json去掉换行
                let templateDataValue  = dictionaryToJson(tdic)
                let picDataValue  = configPicData()
                
            
                if OfflineFileBoard.isUseFileClipPlatform() {
                    TempClipFileManager.shared.uploadFile(files: newFile, vouId: vouId, pic_data: picDataValue, pic_data_details: deJson, templateData: templateDataValue, menu_nm: module_nm) {
                        
                        success()
                        
                    } error: { err in
                        error(err)
                    }
                } else {
                    KSNetwork.shared.doRequest(API.temp(.tempUploadFileApi(templateData: templateDataValue, pic_data: picDataValue,pic_data_details: deJson, images: newFile)), successHandle: { (data:BaseResult<OperateResult>) in
                        if data.flag == TRUE {
//                            KSToast("保存文件成功")
                            success()
                        } else {
                            error(.businessFailure(data.errorCombine.unwrap))
                        }
                    }) { kserror in
                        
                        for i in 0..<newFile.count {
                            let item =  newFile[i]
                            let onedetail = "[\(totalJsonArr[i])]"
                            
                            let out_picDataValue  = configPicData(withoutDt: true)
                            
                            
                            if FMDBHelper.shared.database == nil {
                                FMDBHelper.shared.openDB(dbname: OutlineDBKey.TableName)
                            }
                            
                            FMDBHelper.shared.insertInto(table: "OUTLINE_FILE", paramValues:
                                                            [("vou_id", vouId),
                                                             ("offline_dt", time),
                                                             ("template_data", templateDataValue),
                                                             ("pic_data", out_picDataValue),
                                                             ("pic_data_details", onedetail),
                                                             ("img_name", item.name.unwrap),
                                                             ("img_data", item.data!),
                                                             ("up_status", "0")])
                        }
                        
      
                        
                        error(kserror)
                    }
                } 
                
            }
        }
        func configPicData(withoutDt:Bool = false) -> String {
            var dic:[String : Any] = ["z_org_id":USERINFO.zOrgId.unwrap,
                                      "z_org_nm":USERINFO.mOrgNm.unwrap,
                                       "m_org_id":USERINFO.mOrgId.unwrap,
                                      "m_org_nm":USERINFO.mOrgNm.unwrap,
                                       "z_updater_id":USERINFO.idKey.unwrap,
                                      "z_updater_nm":USERINFO.usrdesc.unwrap,
                                      "vou_id":vouId,
                                      "module_id":module_id,
                                      "z_update_dt":Date.today,
            ]
            if withoutDt {
                dic.updateValue(Date.nowTimeToSecond, forKey: "offline_dt")
            }
            
            
           return dictionaryToJson(dic)
        }
 
        
    }
}
// MARK: - 删除图片  通用模板
public func deleImage_temp(templateDic:[[String:Any]],idkey:String,vou_id:String,module_id:String,temp:TemplateModel ,success:@escaping (()->())) {
 
    let tdic = findTempDicAndDeal(templateDic: templateDic, item: temp)
    
    
    KSNetwork.shared.doRequest(API.temp(.deletePicture_temp(pic_id: idkey,vou_id:vou_id,module_id:module_id,templateData: dictionaryToJson(tdic))), successHandle: { (data:BaseResult<OperateResult>) in
        if data.flag == TRUE {
            KSToast("删除成功")
            success()
        } else {
            KSToast(data.errorCombine.unwrap)
        }
    })
}
// 模板生成字典  有默认值的都取出来
func temp2Dic(_ tempA:[TemplateModel],rootTemp:MainTempModel) -> [String:Any] {
    
    
    var detailDic = [String:Any]()
    for item in tempA {
        
        let pre = item.field_nm.unwrap
        var suf = item.default_value.unwrap
        
        //            1:当天,2:当月第一天;3:前30天;4:前60天;5:前90天
        if item.field_type.unwrap == TemplateType.date.rawValue {
            suf = dateId2Value(item.date_default_value.unwrap)
            
        } else if item.field_type.unwrap == TemplateType.datetime.rawValue {
            switch item.date_time_default_value.unwrap {
            case "1":
                suf = Date.nowTimeToSecond
            default:
                break
            }
        } else if item.field_type.unwrap == TemplateType.month.rawValue {
            if item.month_default_value.unwrap == "" {
                suf = ""
            } else {
                suf = Date.preMonths(intTran(item.month_default_value))
            }
            
        } else {
            
            suf = getDolVal(item.default_value.unwrap,rootTemp: rootTemp).0
        }
        
        detailDic.updateValue(suf, forKey: pre)
        
    }
    detailDic.updateValue(TRUE, forKey: TKey.openx)
    return detailDic
}



// 表达式  88>=0&&88<=100  返回bool
// 输入表达式   主字典   细表组 字典  
func expressionReplace(_ str:String,main:[String:Any]? = nil,currDet:[String:Any]? = nil,rootTemp:MainTempModel) -> Bool {
    TempLog("\n\n\n表达式开始")
    TempLog(str)
    
    // 带有括号的表达式，优先计算括号
    if str.contains("(") {
        let re = str.dealParenthesis(str: str)
        
        var newDic:[String:Bool] = [:]
        for item in re.1 {
            let xxRe = dealspandEx(spandStr: item.value,main: main,currDet: currDet, rootTemp: rootTemp)
            newDic.updateValue(xxRe, forKey: item.key)
        }
        var replaceStr =  re.0
        for nItem in newDic {
            replaceStr = replaceStr.replacingOccurrences(of: nItem.key, with: "\(nItem.value)")
        }
        
        return dealspandEx(spandStr: replaceStr,main: main,currDet: currDet, rootTemp: rootTemp)
    } else {
        // 没有括号的平直表达式
        return dealspandEx(spandStr: str,main: main,currDet: currDet, rootTemp: rootTemp)
    }
    
    
    
}
// 处理没括号的平直表达式
func dealspandEx(spandStr:String,main:[String:Any]? = nil,currDet:[String:Any]? = nil, rootTemp: MainTempModel) -> Bool {
    var valiFlag = false
    if spandStr.contains("&&") {
        valiFlag = true
        let cArr = spandStr.components(separatedBy: "&&")
        for itemA in cArr {
            let flagX = expressionVali(itemA,main: main,currDet: currDet, rootTemp: rootTemp)
            valiFlag = valiFlag && flagX
        }
        
    } else if spandStr.contains("||") {
        valiFlag = false
        let cArr = spandStr.components(separatedBy: "||")
        for itemA in cArr {
            let flagX = expressionVali(itemA,main: main,currDet: currDet, rootTemp: rootTemp)
            valiFlag = valiFlag || flagX
        }
    } else {
        valiFlag = expressionVali(spandStr,main: main,currDet: currDet, rootTemp: rootTemp)
    }
    return valiFlag
}
// <= >= < >
func expressionVali(_ str:String,main:[String:Any]? = nil,currDet:[String:Any]? = nil,rootTemp:MainTempModel) -> Bool {
    var valiFlag = false
    KSLog("原始：\(str)")
    let changeStr = getDolVal(str,main: main,currDet: currDet,rootTemp: rootTemp).0
    KSLog("转换：\(changeStr)")
    if changeStr.contains("#") {
        // 包含#说明日期无法计算，直接放过
        valiFlag = true
    } else if changeStr.contains("<=") {
        let pre = doubleTran(changeStr.preChar(char: "<="))
        let suf = doubleTran(changeStr.sufChar(char: "<="))
        valiFlag = pre <= suf
    } else if changeStr.contains(">=") {
        let pre = doubleTran(changeStr.preChar(char: ">="))
        let suf = doubleTran(changeStr.sufChar(char: ">="))
        valiFlag = pre >= suf
        
    } else if changeStr.contains("<") {
        let pre = doubleTran(changeStr.preChar(char: "<"))
        let suf = doubleTran(changeStr.sufChar(char: "<"))
        valiFlag = pre < suf
    } else if changeStr.contains(">") {
        let pre = doubleTran(changeStr.preChar(char: ">"))
        let suf = doubleTran(changeStr.sufChar(char: ">"))
        valiFlag = pre > suf
    } else if changeStr.contains("!=") {
        // 不等于符号支持字符串 和 数字
        let pre = changeStr.preChar(char: "!=")
        let suf = changeStr.sufChar(char: "!=")
        valiFlag = pre != suf
    } else if changeStr.contains("==") {
        // 等于符号支持字符串 和 数字
        
        let pre = changeStr.preChar(char: "==")
        let suf = changeStr.sufChar(char: "==")
        valiFlag = pre == suf
    } else if changeStr == "true" {
        return true
    } else if changeStr == "false" {
        return false
    } else {
        alertUtil(title: "未识别表达式",message: "\(str)---\(changeStr)", operateS: [nameAction(name: "确认", action: { (_) in
            
        })])
    }
    KSLog("结果： \(valiFlag)\n")
    return valiFlag
}




func caculeTool(_ str:String) -> Double {
    
    
    let tempStr = str
    
    var numArr:[Double] = []
    var charArr:[String] = []
    var temps = ""
  
    tempStr.forEach { c in
        let s = String(c)
        if s == "+" ||  s == "-" || s == "*" || s == "/" {
            if let db = Double(temps) {
                numArr.append(db)
             } else {
                numArr.append(0)
             }
            charArr.append(s)
            temps = ""
        } else {
            temps += s
        }
    }
    if temps != "" {
        if let db = Double(temps) {
            numArr.append(db)
         } else {
            numArr.append(0)
        }
     }
    
//    KSLog("检测000")
//    KSLog(numArr)
//    KSLog(charArr)
  
        while charArr.contains("*") || charArr.contains("/") {
            
            for i in 0..<charArr.count {
                if charArr[i] == "*" || charArr[i] == "/" {
                    if  numArr.count > (i+1) {
                        if charArr[i] == "*"  {
                            numArr[i] = numArr[i] * numArr[i+1]
                        }
                        if charArr[i] == "/"  {
                            numArr[i] = numArr[i] / numArr[i+1]
                        }
                        numArr.remove(at: i+1)
                        charArr.remove(at: i)
                        break
                    }
                   
                }
             }
//            KSLog(numArr)
//            KSLog(charArr)
        }
        var counter = 0  // 计数器变量，初始化为0
        while charArr.count > 0 {
            for i in 0..<charArr.count {
                if  numArr.count > (i+1) {
                    if charArr[i] == "-" || charArr[i] == "+" {
                        if charArr[i] == "-" {
                            numArr[i] = numArr[i] - numArr[i+1]
                        }
                        if charArr[i] == "+" {
                            numArr[i] = numArr[i] + numArr[i+1]
                        }
                        numArr.remove(at: i+1)
                        charArr.remove(at: i)
                        break
                    }
                }
               
            }
            
//            KSLog(numArr)
//            KSLog(charArr)
            // 防止意外死循环，设置上限跳出
            counter += 1
            if counter > 50 {
                break
            }
        }
        let result = numArr.first.isSome ? numArr.first! : 0
        return result
 
    
   
    
    
    
    
}

// 模板专用计算文本高度算法 计算高度 自适应高度  lineSpacing：行间距
func tempSpCountHeight(_ contentStr:String,lineSpacing:CGFloat? = nil) -> CGFloat {
    // 手动计算文本高度
    
    if lineSpacing.isSome {
        
        let paraph = NSMutableParagraphStyle()
        //将行间距设置为
        paraph.lineSpacing = lineSpacing!
        
//        attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paraph, range: NSRange(location: 0, length: attributedString.length))
        
        let hhh = contentStr.heightWithStringAttributes(attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 17),NSAttributedString.Key.paragraphStyle:paraph], fixedWidth: KSGlobal.screenW - 40) + 25
        return hhh
    } else {
        let hhh = contentStr.heightWithStringAttributes(attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 17)], fixedWidth: KSGlobal.screenW - 40) + 25
        return hhh
    }
    
    
}



// 是否可编辑
func isEnableJ(_ model:TemplateModel,auCombine:AuditParamCombine?,exType:OperateType) -> Bool {
  
    
    if let auCombine = auCombine {
        if auCombine.model.nodeId == "root" {
            // root 节点的控制开关，回到了单据本身，大部分都是开的,按照原单据的修改逻辑来走  fix
            return  isEnableJ_pureTemp(model, exType: .fix)
        } else {
            let formItems = auCombine.info.formItems
            if model.ymkD_idNameFlag == "name" {
                let fffA = formItems.filter { $0.title == model.field_annotation }
                if fffA.count > 0 {
                    let perm = fffA.first!.perm
                   if perm == "R" {
                       return false
                   } else {
                        return true
                   }
                } else {
                    return isEnableJ_pureTemp(model, exType: exType)
                }
            } else {
                let fffA = formItems.filter { $0.columnName == model.field_nm}
                if fffA.count > 0 {
                    let perm = fffA.first!.perm
                    if perm == "R" {
                        return false
                    } else {
                        
                        
                        if model.ymkD_idNameFlag == "id" {
                            // 如果是id,会转给name编辑
                            return false
                        } else {
                            return true
                        }
                        
                      
                    }
                } else {
                    return  isEnableJ_pureTemp(model, exType: exType)
                }
            }
        }
        

       
        
    } else {
      return  isEnableJ_pureTemp(model, exType: exType)
       
    }
    
 
    
}
func isEnableJ_pureTemp(_ model:TemplateModel,exType:OperateType) -> Bool {
    if exType == .add {
        return (model.isEditEnable.unwrap == "1" || model.isEditEnable == "2")
    } else if exType == .fix {
        return model.isEditEnable.unwrap == "1"
    } else {
        return false
    }
}

// 是否显示的处理
func isShowJ(_ model:TemplateModel,auCombine:AuditParamCombine?,exType:OperateType?) -> Bool {
 
    if let auCombine = auCombine {
        
        let formItems = auCombine.info.formItems
    
        
        if model.ymkD_idNameFlag == "name" {
            // 下拉选，去找id
            let fffA = formItems.filter { $0.title == model.field_annotation }
            if fffA.count > 0 {
                let perm = fffA.first!.perm
               if perm == "H" {
                   return false
               } else {
                    return true
               }
            } else {
                return isShowJ_pureTemp(model, exType: exType)
            }

        } else {
            let fffA = formItems.filter { $0.columnName == model.field_nm }
            if fffA.count > 0 { // 审批那边下发控制
               
                    let perm = fffA.first!.perm
                   if perm == "H" {
                       return false
                   } else {
                       
                       if model.ymkD_idNameFlag == "id" {
                           // 如果是id,会转给name显示
                           return false
                       } else {
                           return true
                       }
    
                   }
 
              
            } else {
                return isShowJ_pureTemp(model, exType: exType)
            }
        }
   
    } else {
        return isShowJ_pureTemp(model, exType: exType)
         
    }
 
   
}
// 纯配置菜单 显示逻辑
func isShowJ_pureTemp(_ model:TemplateModel,exType:OperateType?) -> Bool {
    if exType == .add {
        return ( model.isFormSHow.unwrap == "1" || model.isFormSHow.unwrap == "2" )
    } else {
        return ( model.isFormSHow.unwrap == "1" || model.isFormSHow.unwrap == "3" )
    }
}



// 计算细表高度  单个控件的高度  和整个单条细表的高度  *配置菜单高度流程*
func  countDetailHeight(_ deCom:DetailsTempCom,auCombine: AuditParamCombine?,exType:OperateType?) -> DetailsTempCom {
    
    var newDeCom = deCom
    
    var detailHeight:CGFloat = 0
    var tempA = deCom.temp
    
    
    for i in 0..<tempA.count {
        let item = tempA[i]
        // 显示的控件  计算高度   不显示的别丢了，原装返回,后续有可能被影响为可显示
        if isShowJ(item,auCombine: auCombine,exType: exType) {
            let textC = any2Str(deCom.dic[item.field_nm.unwrap])
            let textC_height = tempSpCountHeight(textC)
         
             
            if item.field_type == TemplateType.file.rawValue {
                detailHeight += singleImgHeight
                tempA[i].oneHeight = singleImgHeight
            } else {
               
                
                var realH:Double = 0
        
                
                if judgeUseVWidge(item) {
                    let vtempHeight = textC_height + vItemTitleHight
                    let maxH = doubleTran(item.field_height) > vtempHeight ? doubleTran(item.field_height) : vtempHeight
                    if maxH >   ItemVHeight {
                        realH = maxH
                     } else {
                        realH =  ItemVHeight
                    }
                } else {
                    let maxH = doubleTran(item.field_height) > textC_height ? doubleTran(item.field_height) : textC_height
                    if maxH > ItemHHeight {
                        realH = maxH
                     } else {
                        realH = ItemHHeight
                    }
                }
               
                
                detailHeight += realH
                tempA[i].oneHeight = realH
                KSLog("-oneH--\(realH)")
                
            }
        }
        
        
    }
    // 稍微预留空间
    detailHeight += 5
    KSLog(detailHeight)
    
    newDeCom.detailHeight = detailHeight
    newDeCom.temp = tempA
    return newDeCom
}
// 添加模板和数据，顺便算高
extension Array<DetailsTempCom> {
    
    mutating func appendAndCountH(_ one:DetailsTempCom,auCombine: AuditParamCombine?,exType:OperateType?) {
        let  newOne = countDetailHeight(one,auCombine:auCombine,exType: exType)
        self.append(newOne)
    }
}



func type2PicType(_ typeStr:String) -> [PictureType] {
    let upArr = typeStr.components(separatedBy: ",").filterDuplicates { $0 }
    var picTypeArr:[PictureType] = []
    for item in upArr {
        if item == "1" { // 拍照
            picTypeArr.append(.takePicture)
        }
        if item == "2" {// 相册
            picTypeArr.append(.albumPicture)
        }
        if item == "3" {// 附件
            picTypeArr.append(.allfile)
        }
        if item == "4" {// 视频
            picTypeArr.append(.videoRecording)
        }
        if item == "5" {// 相册视频
            picTypeArr.append(.albumVideo)
        }
    }
    return picTypeArr
}

func go2TempUtil(pvc:UIViewController,rtemp:MainTempModel) {
     
   
        if rtemp.setGesturePwd {
            let vc = GesturePasswordViewController()
            vc.goNextVC = { (flag) in
                
                if flag == true {
                    
                    goContinue()
                }
            }
            pvc.present_FullScreen(to: vc)
            
        } else {
            goContinue()
        }
   
    
    func goContinue() {
        if rtemp.referModels.count > 0 {// 有引用的子菜单
            let vc = KSTempSegVC()
            vc.rootTemp = rtemp
            pvc.navigationController?.pushViewController(vc, animated: true)
        } else {
            let vc = KSTempListVC()
            vc.rootTemp = rtemp
            pvc.navigationController?.pushViewController(vc, animated: true)
        }
    }
  
    
}


func fetchTempData(menuid:String,success:@escaping(([TemplateModel],[[String:Any]])->())) {
    KSNetwork.shared.doRequest(API.temp(.getFieldTemplateInfoByMenuId(menu_id: menuid))) { (data:BaseResult<TemplateModel>) in
        if data.flag == TRUE {
            if let infos = data.infoArrCombine {
         
                success(infos,data.infoDicArr)
            }
        } else {
            KSToast(data.errorCombine.unwrap)
        }
    }
}

// 字符数组 转化为  菜单数组  并且过滤权限
func menuArrDealed(_ arr:[String]) -> [MenuItem] {
    var showMenuItem = [MenuItem]()
    let menuItem = arr.compactMap { one -> MenuItem? in
        let mArr = MenuPool.filter{ $0.desc.unwrap == one}
        return mArr.first
    }
    if DeveloperTool.shared.GetAllowAllLimit() {
        showMenuItem = menuItem
    } else {
        showMenuItem = menuItem.filter {  one -> Bool in
            // 包含逗号的双权限匹配 中一个就算有权限
            if one.resId.unwrap.contains(",") {
                let residArr = one.resId.unwrap.components(separatedBy: ",")
                var flag = false
                for item in residArr {
                    if let _ = LimitDic[item] {
                        flag = true
                    }
                }
                return flag
                
            } else {
                if let _ = LimitDic[one.resId.unwrap] {
                    return true
                } else if one.resId.unwrap == "0" {
                    return true
                } else if one.resId.unwrap == "" {
                    return true
                } else {
                    return false
                }
            }
            
        }
    }
    return showMenuItem
}

struct BackFillStruct {
    var fromParam = ""
    var toParam = ""
    var detFlag = ""
}



import ObjectMapper

struct Newflow: Mappable {
    
  
   var progress = [TodopProgress]()
 
    init?(map: Map) {
        
    }
    // Mappable
    mutating func mapping(map: Map) {
     
        progress <- map["progress"]
      

    }
    
}
struct MxtableModel: Mappable {
    var c_enable_group: String?
    var c_group_title: String?
    var table_title:String?
    var table = [TableCellModel]()
    init?(map: Map) {
     }
    // Mappable
    mutating func mapping(map: Map) {
     
        table_title <- map["table_title"]
        table <- map["table"]
        c_enable_group <- map["c_enable_group"]
        c_group_title <- map["c_group_title"]
      }
    
}

struct TableCellModel: Mappable {
    var dt_table = [TableCellModel]()

    var data = [TableDataModel]()
    var rows:Int?
    init?(map: Map) {
    }
    // Mappable
    mutating func mapping(map: Map) {
        data <- map["data"]
        rows <- map["rows"] 
        dt_table <- map["dt_table"]
      }
    
}

struct TableDataModel: Mappable {
     var comments:String?
    var column:String?
    var value:String?
    
      init?(map: Map) {
     }
    // Mappable
    mutating func mapping(map: Map) {
     
        comments <- map["comments"]
        column <- map["column"]
        value <- (map["value"],StringTransform())
      }
    
}

 
struct TodoFile: Mappable {
    
    var file_name:String?
    var file_url:String?

    var annex_yewu:String?
 
    init?(map: Map) {
        
    }
    // Mappable
    mutating func mapping(map: Map) {
        file_name <- map["file_name"]
        file_url <- map["file_url"]
        annex_yewu <- map["annex_yewu"]


    }
    
}

struct TodoResult: Mappable {
    
    var formItems = [TodoFormItems]()
    var mxtable = [MxtableModel]()
   var progress = [TodopProgress]()
    var file = [TodoFile]()

    var processDefName:String?
    var operationPerm:OperationPerm?
    var newflow:Newflow?
    var report_url: String?
    init?(map: Map) {
        
    }
    // Mappable
    mutating func mapping(map: Map) {
        processDefName <- map["processDefName"]
        newflow <- map["newflow"]
        mxtable <- map["mxtable"]
        file <- map["file"]

        formItems <- map["formItems"]
        progress <- map["progress"]
        operationPerm <- map["operationPerm"]
        report_url <- map["report_url"]
    }
    
}
enum JueseTypeEnum {
    //submiter 提交人  取消提交  催办
   //auditer 审核人   同意 指定改单
    //noticer 知会者   可以评论
    //completed  完成的单据     可以知会别人 和已阅
    
    // 旁观者  从配置菜单过来，单纯看看审批流程  无按钮
    // 填单人，有一个填写完成按钮
    // bohui  驳回的   一个已阅按钮
    // 评论者  可以评论
    case submiter,auditer,noticer,completed, viewer,writer,bohui,commenter
}

class AuditProcessAppear:NSObject {
    
    var jueseType:JueseTypeEnum = .auditer
    @discardableResult
    func jueseType(_ value:JueseTypeEnum) -> AuditProcessAppear {
        self.jueseType = value
        return self
    }
   
   
}
 
// 基地树   id  name   公司树  id   name
class OrgTreeNode: Mappable {
    
    var name: String?
    var pId:String?
    var id:String?
    
    var children:[OrgTreeNode]?
    var level:Int?
    var color:UIColor!
    var open = true // 树节点的展开与关闭
    var selected = false // 选中标识
    var matched = true // 搜索的匹配标识，不匹配不显示
    var type:OrgSelectType!
    // 以下为猪场特有字段
    var zDjJc:String?
    var mOrgNm: String?
    var mOrgId:String?
    var nameNew:String?
    var zAreaId:String?
    var zAreaNm:String?
    required init?(map: Map) {
         
    }
    // Mappable
    func mapping(map: Map) {
        pId <- (map["pId"],StringTransform())
        name <- map["name"]
        id <- (map["id"],StringTransform())
        children <- map["children"]
        zDjJc <- map["z_dj_jc"]
        mOrgNm <- map["m_org_nm"]
        mOrgId <- (map["m_org_id"],StringTransform())
        nameNew <- map["name_new"]
        zAreaId <- (map["z_area_id"],StringTransform())
        zAreaNm <- map["z_area_nm"]
        
    }
}
